from django.core.cache import caches
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from api.consts import USERNAME_PATTERN
from common.utils import to_md5_hex
from common.models import District, HouseType, Agent, Estate, HouseInfo, Tag, HousePhoto, User, UserRole, Role


class DistrictSimpleSerializer(serializers.ModelSerializer):
    """地区基本信息序列化器"""

    class Meta:
        model = District
        fields = ('distid', 'name')


class DistrictDetailSerializer(serializers.ModelSerializer):
    """地区详情信息序列化器"""
    cities = serializers.SerializerMethodField()

    @staticmethod
    def get_cities(district):
        queryset = District.objects.filter(parent=district)
        return DistrictSimpleSerializer(queryset, many=True).data

    class Meta:
        model = District
        fields = ('distid', 'name', 'intro', 'cities')


class HouseTypeSerializer(serializers.ModelSerializer):
    """户型序列化器"""

    class Meta:
        model = HouseType
        fields = '__all__'


class EstateSimpleSerializer(serializers.ModelSerializer):
    """楼盘基本信息序列化器"""

    class Meta:
        model = Estate
        fields = ('estateid', 'name', 'hot')


class EstateDetailSerializer(serializers.ModelSerializer):
    """楼盘详情信息序列化器"""
    district = serializers.SerializerMethodField()

    @staticmethod
    def get_district(estate):
        return DistrictSimpleSerializer(estate.district).data

    class Meta:
        model = Estate
        fields = '__all__'


class EstateSerializer(serializers.ModelSerializer):
    """楼盘序列化器"""

    def validate(self, attrs):
        if len(attrs.get('name', '')) < 2:
            raise ValidationError('无效的楼盘名字')
        if attrs.get('hot', 0) < 0:
            raise ValidationError('楼盘热度不能是负数')
        return attrs

    class Meta:
        model = Estate
        fields = '__all__'


class AgentSimpleSerializer(serializers.ModelSerializer):
    """经理人基本信息序列化器"""

    class Meta:
        model = Agent
        fields = ('agentid', 'name', 'tel', 'servstar')


class AgentDetailSerializer(serializers.ModelSerializer):
    """经理人详情信息序列化器"""
    estates = serializers.SerializerMethodField()

    @staticmethod
    def get_estates(agent):
        return EstateSimpleSerializer(agent.estates, many=True).data

    class Meta:
        model = Agent
        fields = '__all__'


class TagSerializer(serializers.ModelSerializer):
    """房源标签序列化器"""

    class Meta:
        model = Tag
        fields = '__all__'


class HouseInfoSerializer(serializers.ModelSerializer):
    """房源序列化器"""

    class Meta:
        model = HouseInfo
        fields = '__all__'


class HouseInfoSimpleSerializer(serializers.ModelSerializer):
    """房源基本信息序列化器"""
    mainphoto = serializers.SerializerMethodField()
    # photocount = serializers.SerializerMethodField()
    district = serializers.SerializerMethodField()
    type = serializers.SerializerMethodField()
    tags = serializers.SerializerMethodField()

    # @staticmethod
    # def get_photocount(houseinfo):
    #     return HousePhoto.objects.filter(house=houseinfo).count()

    @staticmethod
    def get_mainphoto(houseinfo):
        return '/static/images/' + houseinfo.mainphoto

    @staticmethod
    def get_district(houseinfo):
        return DistrictSimpleSerializer(houseinfo.district_level3).data

    @staticmethod
    def get_type(houseinfo):
        return HouseTypeSerializer(houseinfo.type).data

    @staticmethod
    def get_tags(houseinfo):
        return TagSerializer(houseinfo.tags, many=True).data

    class Meta:
        model = HouseInfo
        fields = ('houseid', 'title', 'area', 'floor', 'totalfloor', 'price', 'priceunit',
                  'mainphoto', 'street', 'district', 'type', 'tags')


class HouseInfoDetailSerializer(serializers.ModelSerializer):
    """房源详情序列化器"""
    district = serializers.SerializerMethodField()
    type = serializers.SerializerMethodField()
    tags = serializers.SerializerMethodField()
    estate = serializers.SerializerMethodField()
    agent = serializers.SerializerMethodField()
    photos = serializers.SerializerMethodField()

    @staticmethod
    def get_district(houseinfo):
        return DistrictSimpleSerializer(houseinfo.district_level3).data

    @staticmethod
    def get_type(houseinfo):
        return HouseTypeSerializer(houseinfo.type).data

    @staticmethod
    def get_tags(houseinfo):
        return TagSerializer(houseinfo.tags, many=True).data

    @staticmethod
    def get_estate(houseinfo):
        return EstateSimpleSerializer(houseinfo.estate).data

    @staticmethod
    def get_agent(houseinfo):
        return AgentSimpleSerializer(houseinfo.agent).data

    @staticmethod
    def get_photos(houseinfo):
        queryset = HousePhoto.objects.filter(house=houseinfo)
        return HousePhotoSerializer(queryset, many=True).data

    class Meta:
        model = HouseInfo
        exclude = ('district_level2', 'district_level3', 'user')


class HousePhotoSerializer(serializers.ModelSerializer):
    """房源照片序列化器"""

    class Meta:
        model = HousePhoto
        fields = ('photoid', 'path')


class RoleSerializer(serializers.ModelSerializer):
    """角色序列化器"""

    class Meta:
        model = Role
        fields = ('roleid', 'rolename')


class UserSimpleSerializer(serializers.ModelSerializer):
    """用户基本信息序列化器"""
    roles = serializers.SerializerMethodField()

    @staticmethod
    def get_roles(user):
        return RoleSerializer(user.roles, many=True).data

    class Meta:
        model = User
        fields = ('userid', 'username', 'realname', 'roles')


class UserCreateSerializer(serializers.ModelSerializer):
    """创建用户序列化器"""
    repassword = serializers.CharField(write_only=True)
    code = serializers.CharField(write_only=True)

    def create(self, validated_data):
        del validated_data['code']
        del validated_data['repassword']
        validated_data['password'] = to_md5_hex(validated_data['password'])
        user = User.objects.create(**validated_data)
        # 将注册用户的默认角色为普通用户
        role = Role.objects.get(roleid=1)
        UserRole.objects.create(user=user, role=role)
        return user

    @staticmethod
    def validate_username(username):
        if not USERNAME_PATTERN.match(username):
            raise ValidationError('用户名由字母数字下划线构成且长度为6-20个字符')
        return username

    @staticmethod
    def validate_password(password):
        if len(password) < 8:
            raise ValidationError('用户密码至少8个字符')
        return password

    def validate(self, attrs):
        if attrs['password'] != attrs['repassword']:
            raise ValidationError('用户密码和确认密码需要保持一致')
        code_from_server = caches['default'].get(attrs['tel'])
        code_from_user = attrs['code']
        if code_from_server != code_from_user:
            raise ValidationError('请输入有效的手机验证码')
        return attrs

    class Meta:
        model = User
        exclude = ('regdate', 'point', 'lastvisit', 'roles')


class UserUpdateSerializer(serializers.ModelSerializer):
    """更新用户序列化器"""
    oldpassword = serializers.CharField(default='')
    newpassword = serializers.CharField(default='')
    repassword = serializers.CharField(default='')

    class Meta:
        model = User
        exclude = ('password', )
